package com.micro.frog.fortune.util;

import java.net.InetAddress;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Nonnull;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 加锁工具类，多副本服务同时执行时，只能允许其中一个服务执行时调用
 * 使用场景： 服务启动时自动执行；定时任务启动时等
 *
 * @author jason.lv
 */
@Slf4j
@Component
public class LockUtil implements ApplicationContextAware {

    private static final String TABLE_NAME_LOCK = "conf_lock";

    private static DataSource dataSource;

    @Override
    public void setApplicationContext(@Nonnull ApplicationContext context) throws BeansException {
        dataSource = context.getBean(DataSource.class);
    }

    /**
     * 加锁
     */
    public static boolean addLock(String lockName, int expired) {
        Connection connection = null;
        Statement statement = null;
        try {
            connection = dataSource.getConnection();
            statement = connection.createStatement();

            if (expired > 0) {
                long timestamp = System.currentTimeMillis() / 1000 - expired;
                // 移除可能存在过期的
                String s = "delete from `conf_lock` where `type`='%s' and unix_timestamp(`create_time`) < %d";
                statement.executeUpdate(String.format(s, lockName, timestamp));
            }

            String sql = "insert into `%s` (`host_name`,`type`) values ('%s','%s')";
            statement.executeUpdate(String.format(sql, TABLE_NAME_LOCK,
                InetAddress.getLocalHost().getHostName() + "-" + Thread.currentThread().getName(), lockName));
            log.warn("成功加锁:{}", lockName);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(connection, statement);
        }
        return false;
    }

    /**
     * 解锁，加锁后执行完成后再调用此方法解锁
     */
    public static void removeLock(String lockName) {
        Connection connection = null;
        Statement statement = null;
        try {
            connection = dataSource.getConnection();
            statement = connection.createStatement();
            String sql = "delete from `%s` where `type`='%s'";
            statement.executeUpdate(String.format(sql, TABLE_NAME_LOCK, lockName));
            log.warn("成功释放锁：{}", lockName);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            close(connection, statement);
        }
    }

    private static void close(Connection connection, Statement statement) {
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (Exception ignored) {
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (Exception ignored) {
        }
    }
}
